package com.yxf.variousshapes3d.shapes;


import com.yxf.variousshapes3d.Point;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import static android.opengl.GLES20.GL_FLOAT;
import static android.opengl.GLES20.glVertexAttribPointer;

public abstract class BaseShape {
    public static final int BYTES_PER_FLOAT = 4;

    public static final int POSITION_COMPONENT_COUNT = 3;
    public static final int COLOR_COMPONENT_COUNT = 4;
    public static final int STRIDE = (POSITION_COMPONENT_COUNT +
            COLOR_COMPONENT_COUNT) * BYTES_PER_FLOAT;
    protected int aPositionLocation;
    protected int aColorLocation;

    protected Point center;
    protected Object mLock = new Object();

    public BaseShape(Point center) {
        this.center = center;
    }

    public void setLocation(int aPositionLocation, int aColorLocation) {
        this.aPositionLocation = aPositionLocation;
        this.aColorLocation = aColorLocation;
    }


    public final void draw() {
        preDraw();
        synchronized (mLock) {
            FloatBuffer vertexData = getVertexData();
            vertexData.position(0);
            glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GL_FLOAT,
                    false, STRIDE, vertexData);
            vertexData.position(POSITION_COMPONENT_COUNT);
            glVertexAttribPointer(aColorLocation, COLOR_COMPONENT_COUNT, GL_FLOAT,
                    false, STRIDE, vertexData);
            drawArrays();
        }
        afterDraw();
    }

    public void initialize() {
        synchronized (mLock) {
            initWithoutLock();
        }
    }

    public static FloatBuffer encodeVertices(float[] vertices) {
        FloatBuffer vertexData = ByteBuffer.allocateDirect(vertices.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexData.put(vertices);
        return vertexData;
    }

    public abstract void initWithoutLock();

    protected abstract FloatBuffer getVertexData();

    protected abstract void drawArrays();

    protected abstract void preDraw();

    protected abstract void afterDraw();

}
